﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Collections;

namespace Hack.Net
{


    ///// 
    ///// Author: Asad Aziz
    ///// Description: State object for reading client data asynchronously.
    /////

    //public class StateObject
    //{
    //    public bool connected = false;	// ID received flag
    //    public Socket workSocket = null;	// Client socket.
    //    public Socket partnerSocket = null;	// Partner socket.
    //    public const int BufferSize = 1024;	// Size of receive buffer.
    //    public byte[] buffer = new byte[BufferSize];// Receive buffer.
    //    public StringBuilder sb = new StringBuilder();//Received data String.
    //    public string id = String.Empty;	// Host or conversation ID
    //    public DateTime TimeStamp;
    //}

    ///// 
    ///// Description: Server is the class to control sockets	/// 
    //public class Server
    //{
    //    protected int portNumber;
    //    protected int maxSockets;
    //    protected int sockCount = 0;
    //    private int convID = 0;
    //    private Timer lostTimer;
    //    private const int numThreads = 1;
    //    private const int timerTimeout = 300000;
    //    private const int timeoutMinutes = 3;
    //    private bool ShuttingDown = false;
    //    protected string title;
    //    protected Hashtable connectedHT = new Hashtable();
    //    protected ArrayList connectedSocks;

    //    //Thread signal.
    //    private ManualResetEvent allDone = new ManualResetEvent(false);
    //    private Thread[] serverThread = new Thread[numThreads];
    //    private AutoResetEvent[] threadEnd = new AutoResetEvent[numThreads];

    //    public Server(int port, string title, string attr)
    //    {
    //        this.portNumber = port;
    //        this.title = title;
    //        this.maxSockets = 10000;
    //        connectedSocks = new ArrayList(this.maxSockets);
    //    }

    //    /// 
    //    /// Description: Start the threads to listen to the port and process
    //    /// messages.
    //    ///

    //    public void Start()
    //    {
    //        // Clear the thread end events
    //        for (int lcv = 0; lcv < numThreads; lcv++)
    //            threadEnd[lcv] = new AutoResetEvent(false);

    //        ThreadStart threadStart1 = new ThreadStart(StartListening);
    //        serverThread[0] = new Thread(threadStart1);
    //        serverThread[0].IsBackground = true;
    //        serverThread[0].Start();

    //        // Create the delegate that invokes methods for the timer.
    //        TimerCallback timerDelegate = new TimerCallback(this.CheckSockets);
    //        // Create a timer that waits one minute, then invokes every 5 minutes.
    //        lostTimer = new Timer(timerDelegate, null, Server.timerTimeout, Server.timerTimeout);

    //    }

    //    /// 
    //    /// Description: Check for dormant sockets and close them.
    //    /// 
    //    /// <param name="eventState">Required parameter for a timer call back
    //    /// method.</param>
    //    private void CheckSockets(object eventState)
    //    {
    //        lostTimer.Change(System.Threading.Timeout.Infinite,
    //        System.Threading.Timeout.Infinite);
    //        try
    //        {
    //            foreach (StateObject state in connectedSocks)
    //            {
    //                if (state.workSocket == null)
    //                {	// Remove invalid state object
    //                    Monitor.Enter(connectedSocks);
    //                    if (connectedSocks.Contains(state))
    //                    {
    //                        connectedSocks.Remove(state);
    //                        Interlocked.Decrement(ref sockCount);
    //                    }
    //                    Monitor.Exit(connectedSocks);
    //                }
    //                else
    //                {
    //                    if (DateTime.Now.AddTicks(-state.TimeStamp.Ticks).Minute > timeoutMinutes)
    //                    {
    //                        RemoveSocket(state);
    //                    }
    //                }
    //            }
    //        }
    //        catch (Exception)
    //        {
    //        }
    //        finally
    //        {
    //            lostTimer.Change(Server.timerTimeout, Server.timerTimeout);
    //        }
    //    }
    //    /// 
    //    /// Decription: Stop the threads for the port listener.
    //    /// 
    //    public void Stop()
    //    {
    //        int lcv;
    //        lostTimer.Dispose();
    //        lostTimer = null;

    //        for (lcv = 0; lcv < numThreads; lcv++)
    //        {
    //            if (!serverThread[lcv].IsAlive)
    //                threadEnd[lcv].Set();	// Set event if thread is already dead
    //        }
    //        ShuttingDown = true;
    //        // Create a connection to the port to unblock the listener thread
    //        Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    //        IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, this.portNumber);
    //        sock.Connect(endPoint);
    //        //sock.Close();
    //        sock = null;

    //        // Check thread end events and wait for up to 5 seconds.
    //        for (lcv = 0; lcv < numThreads; lcv++)
    //            threadEnd[lcv].WaitOne(5000, false);
    //    }

    //    /// 
    //    /// Decription: Open a listener socket and wait for a connection.
    //    /// 
    //    private void StartListening()
    //    {
    //        // Establish the local endpoint for the socket.
    //        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, this.portNumber);
    //        // Create a TCP/IP socket.
    //        Socket listener = new Socket(AddressFamily.InterNetwork,
    //        SocketType.Stream, ProtocolType.Tcp);

    //        // Bind the socket to the local endpoint and listen for incoming connections.

    //        try
    //        {
    //            listener.Bind(localEndPoint);
    //            listener.Listen(1000);

    //            while (!ShuttingDown)
    //            {
    //                // Set the event to nonsignaled state.
    //                allDone.Reset();
    //                // Start an asynchronous socket to listen for connections.

    //                listener.BeginAccept(new AsyncCallback(this.AcceptCallback), listener);

    //                // Wait until a connection is made before continuing.
    //                allDone.WaitOne();
    //            }
    //        }
    //        catch (Exception e)
    //        {
    //            threadEnd[0].Set();
    //        }
    //    }

    //    /// 
    //    /// Decription: Call back method to accept new connections.
    //    /// 
    //    /// <param name="ar">Status of an asynchronous operation.</param>
    //    private void AcceptCallback(IAsyncResult ar)
    //    {
    //        // Signal the main thread to continue.
    //        allDone.Set();
    //        // Get the socket that handles the client request.
    //        Socket listener = (Socket)ar.AsyncState;
    //        Socket handler = listener.EndAccept(ar);

    //        // Create the state object.
    //        StateObject state = new StateObject();
    //        state.workSocket = handler;
    //        state.TimeStamp = DateTime.Now;

    //        try
    //        {
    //            Interlocked.Increment(ref sockCount);
    //            Monitor.Enter(connectedSocks);
    //            connectedSocks.Add(state);
    //            Monitor.Exit(connectedSocks);

    //            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(this.ReadCallback), state);
    //            if (sockCount > this.maxSockets)
    //            {
    //                RemoveSocket(state);
    //                //handler.Shutdown(SocketShutdown.Both);
    //                //handler.Close();
    //                handler = null;
    //                state = null;
    //            }
    //        }
    //        catch (SocketException es)
    //        {
    //            RemoveSocket(state);
    //        }
    //        catch (Exception e)
    //        {
    //            RemoveSocket(state);
    //        }
    //    }

    //    /// 
    //    /// Decription: Call back method to handle incoming data.
    //    /// 
    //    /// <param name="ar">Status of an asynchronous operation.</param>
    //    protected void ReadCallback(IAsyncResult ar)
    //    {
    //        String content = String.Empty;
    //        // Retrieve the state object and the handler socket
    //        // from the async state object.
    //        StateObject state = (StateObject)ar.AsyncState;
    //        /*r />*/
    //        Socket handler = state.workSocket;
    //        try
    //        {
    //            // Read data from the client socket.
    //            int bytesRead = handler.EndReceive(ar);

    //            if (bytesRead > 0)
    //            {
    //                // There might be more data, so store the data received so far.
    //                Monitor.Enter(state);
    //                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
    //                Monitor.Exit(state);
    //                // Check for end-of-file tag.
    //                // If it is not there, read more data.
    //                content = state.sb.ToString();
    //                //if (content.IndexOf("<eof>") > -1)
    //                if ((content.Length > 0) && ((content[0] != '<') ||
    //                ((content[0] == '<') && (content.IndexOf("</eof>") > -1))))
    //                {
    //                    // All the data has been read from the
    //                    // client. Display it on the console.
    //                    //Console.WriteLine("Read {0} bytes from socket.\nData: {1}",
    //                    //	content.Length, content);
    //                    // Process the received message
    //                    state.TimeStamp = DateTime.Now;
    //                    HandleMessages(state, content);

    //                    // Echo the data back to the client.
    //                    // Send(state, content);
    //                    //state.sb.Length = 0;
    //                }
    //                else
    //                {
    //                    // Not all data received. Get more.
    //                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(this.ReadCallback), state);
    //                }
    //            }
    //            else
    //            {	// Disconnected
    //                RemoveSocket(state);
    //            }
    //        }
    //        catch (System.Net.Sockets.SocketException es)
    //        {
    //            RemoveSocket(state);
    //            if (es.ErrorCode != 64)
    //            {
    //                Console.WriteLine(string.Format("ReadCallback Socket Exception: {0}, {1}.", es.ErrorCode, es.ToString()));
    //            }
    //        }
    //        catch (Exception e)
    //        {
    //            RemoveSocket(state);
    //            if (e.GetType().FullName != "System.ObjectDisposedException")
    //            {
    //                Console.WriteLine(string.Format("ReadCallback Exception: {0}.", e.ToString()));
    //            }
    //        }
    //    }

    //    /// 
    //    /// Decription: Send the given data string to the given socket.
    //    /// 
    //    /// <param name="sock">Socket to send data to.</param>
    //    /// <param name="data">The string containing the data to send.</param>
    //    protected void Send(Socket sock, string data)
    //    {
    //        // Convert the string data to byte data using ASCII encoding.
    //        byte[] byteData = Encoding.ASCII.GetBytes(data);

    //        // Begin sending the data to the remote device.
    //        if (byteData.Length > 0)
    //            sock.BeginSend(byteData, 0, byteData.Length, 0,
    //            new AsyncCallback(this.SendCallback), sock);
    //    }

    //    /// 
    //    /// Decription: Call back method to handle outgoing data.
    //    /// 
    //    /// <param name="ar">Status of an asynchronous operation.</param>
    //    protected void SendCallback(IAsyncResult ar)
    //    {
    //        // Retrieve the socket from the async state object.
    //        Socket handler = (Socket)ar.AsyncState;
    //        try
    //        {
    //            // Complete sending the data to the remote device.
    //            int bytesSent = handler.EndSend(ar);
    //        }
    //        catch (Exception e)
    //        {
    //        }
    //    }

    //    /// 
    //    // Description: Find on socket using the identifier as the key.
    //    /// 
    //    /// <param name="id">The identifier key associated with a socket.</param>

    //    private Socket FindID(string id)
    //    {
    //        Socket sock = null;
    //        Monitor.Enter(connectedHT);
    //        if (connectedHT.ContainsKey(id))
    //            sock = (Socket)connectedHT[id];
    //        Monitor.Exit(connectedHT);
    //        return sock;
    //    }

    //    /// 
    //    /// Description: Place the given socket in the connected list.
    //    ///
    //    /// Notes:
    //    /// 1) Get the Member ID from the command
    //    /// 2) Add the socket to the connected socket list with its Member ID
    //    /// 
    //    /// <param name="state">The state object containing the socket info.</param>
    //    /// <param name="command">The XML-based message containing the ID that
    //    /// needs to be parsed.</param>
    //    /// <param name="content">Not used in the base method.</param>

    //    virtual protected bool StuffList(StateObject state, string command,
    //    ref string content)
    //    {
    //        Socket sock = state.workSocket;
    //        string hostID = ReadXML(command, Server.msgConnect, this.connectAttr);

    //        if (hostID != null)
    //        {
    //            state.id = hostID;
    //            if (hostID == Server.webServer)
    //            {
    //                Console.WriteLine(string.Format("Host control socket connected {0}!", this.title));
    //                return true;
    //            }

    //            // Add to connected list
    //            Monitor.Enter(connectedHT);
    //            if (connectedHT.ContainsKey(hostID))
    //            {
    //                object val = connectedHT[hostID];
    //                connectedHT[hostID] = sock;
    //                connectedHT.Add(sock, val);
    //                Console.WriteLine(string.Format("Socket found in Hashtable!", this.title));
    //            }
    //            else
    //            {
    //                connectedHT.Add(hostID, sock);
    //                connectedHT.Add(sock, hostID);
    //                Console.WriteLine(string.Format("Socket not found, adding a new socket to hashtable!", this.title));
    //            }
    //            Monitor.Exit(connectedHT);
    //            Console.WriteLine(string.Format("Socket was moved to connected {0} list!", this.title));
    //            return true;
    //        }
    //        return false;
    //    }

    //    /// 
    //    /// Description: Remove the socket contained in the given state object
    //    /// from the connected array list and hash table, then close the socket.
    //    /// 
    //    /// <param name="state">The StateObject containing the specific socket
    //    /// to remove from the connected array list and hash table.</param>
    //    virtual protected void RemoveSocket(StateObject state)
    //    {
    //        Socket sock = state.workSocket;
    //        Monitor.Enter(connectedSocks);
    //        if (connectedSocks.Contains(state))
    //        {
    //            connectedSocks.Remove(state);
    //            Interlocked.Decrement(ref sockCount);
    //        }
    //        Monitor.Exit(connectedSocks);
    //        Monitor.Enter(connectedHT);

    //        if ((sock != null) && (connectedHT.ContainsKey(sock)))
    //        {
    //            object sockTemp = connectedHT[sock];
    //            if (connectedHT.ContainsKey(sockTemp))
    //            {
    //                if (connectedHT.ContainsKey(connectedHT[sockTemp]))
    //                {
    //                    connectedHT.Remove(sock);
    //                    if (sock.Equals(connectedHT[sockTemp]))
    //                    {
    //                        connectedHT.Remove(sockTemp);
    //                    }
    //                    else
    //                    {
    //                        object val, key = sockTemp;
    //                        while (true)
    //                        {
    //                            val = connectedHT[key];
    //                            if (sock.Equals(val))
    //                            {
    //                                connectedHT[key] = sockTemp;
    //                                break;
    //                            }
    //                            else if (connectedHT.ContainsKey(val))
    //                                key = val;
    //                            else	// The chain is broken
    //                                break;
    //                        }
    //                    }
    //                }
    //                else
    //                {
    //                    Console.WriteLine(string.Format("Socket is not in the {0} connected hash table!", this.title));
    //                }
    //            }
    //        }
    //        Monitor.Exit(connectedHT);

    //        if (sock != null)
    //        {
    //            //if (sock.Connected)
    //            // sock.Shutdown(SocketShutdown.Both);
    //            sock.Close();
    //            sock = null;
    //            state.workSocket = null;
    //            state = null;

    //        }
    //    }
    //}

     /// &ltsummary>
    /// Author: Asad Aziz
    /// Description: State object for reading client data asynchronously.
    /// </summary>

    public class StateObject
    {
        public bool connected = false;    // ID received flag
        public Socket workSocket = null;    // Client socket.
        public Socket partnerSocket = null;    // Partner socket.
        public const int BufferSize = 1024;    // Size of receive buffer.
        public byte[] buffer = new byte[BufferSize];// Receive buffer.
        public StringBuilder sb = new StringBuilder();//Received data String.
        public string id = String.Empty;    // Host or conversation ID
        public DateTime TimeStamp;
    }

    ///&ltsummary>
    /// Author: Asad Aziz
    /// Description: Server is the class to control sockets  
    ///</summary>
    public class Server
    {
        protected int portNumber;
        protected int maxSockets;
        protected int sockCount = 0;
        private int convID = 0;
        private Timer lostTimer;
        private const int numThreads = 1;
        private const int timerTimeout = 300000;
        private const int timeoutMinutes = 3;
        private bool ShuttingDown = false;
        protected string title;
        protected Hashtable connectedHT = new Hashtable();
        protected ArrayList connectedSocks;

        //Thread signal.
        private ManualResetEvent allDone = new ManualResetEvent(false);
        private Thread[] serverThread = new Thread[numThreads];
        private AutoResetEvent[] threadEnd = new AutoResetEvent[numThreads];


        public Server(int port, string title, string attr)
        {
            this.portNumber = port;
            this.title = title;
            this.maxSockets =10000;
            connectedSocks = new ArrayList(this.maxSockets);
        }


        /// &ltsummary>
        /// Description: Start the threads to listen to the port and process
        /// messages.
        /// </summary>

        public void Start()
        {
            // Clear the thread end events
            for (int lcv = 0; lcv < numThreads; lcv++)
                threadEnd[lcv] = new AutoResetEvent(false);

            ThreadStart threadStart1 = new ThreadStart(StartListening);
            serverThread[0] = new Thread(threadStart1);
            serverThread[0].IsBackground = true;
            serverThread[0].Start();

            // Create the delegate that invokes methods for the timer.
            TimerCallback timerDelegate = new TimerCallback(this.CheckSockets);
            //Create a timer that waits one minute, then invokes every 5 minutes.
            lostTimer = new Timer(timerDelegate, null, Server.timerTimeout, Server.timerTimeout);

        }

        /// &ltsummary>
        /// Description: Check for dormant sockets and close them.
        /// </summary>
        /// &ltparam name="eventState">Required parameter for a timer call back
        /// method.</param>
        private void CheckSockets(object eventState)
        {
            lostTimer.Change(System.Threading.Timeout.Infinite,
                System.Threading.Timeout.Infinite);
            try
            {
                foreach (StateObject state in connectedSocks)
                {
                    if (state.workSocket == null)
                    {    // Remove invalid state object
                        Monitor.Enter(connectedSocks);
                        if (connectedSocks.Contains(state))
                        {
                            connectedSocks.Remove(state);
                            Interlocked.Decrement(ref sockCount);
                        }
                        Monitor.Exit(connectedSocks);
                    }
                    else
                    {
                        if (DateTime.Now.AddTicks(-state.TimeStamp.Ticks).Minute > timeoutMinutes)
                        {
                            RemoveSocket(state);
                        }
                    }
                }
            }
            catch (Exception)
            {
            }
            finally
            {
                lostTimer.Change(Server.timerTimeout, Server.timerTimeout);
            }
        }
        /// &ltsummary>
        /// Decription: Stop the threads for the port listener.
        /// </summary>
        public void Stop()
        {
            int lcv;
            lostTimer.Dispose();
            lostTimer = null;

            for (lcv = 0; lcv < numThreads; lcv++)
            {
                if (!serverThread[lcv].IsAlive)
                    threadEnd[lcv].Set();    // Set event if thread is already dead
            }
            ShuttingDown = true;
            // Create a connection to the port to unblock the listener thread
            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, this.portNumber);
            sock.Connect(endPoint);
            //sock.Close();
            sock = null;

            // Check thread end events and wait for up to 5 seconds.
            for (lcv = 0; lcv < numThreads; lcv++)
                threadEnd[lcv].WaitOne(5000, false);
        }


          /// &ltsummary>
        /// Decription: Open a listener socket and wait for a connection.
        /// </summary>

        private void StartListening()
        {
            // Establish the local endpoint for the socket.
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, this.portNumber);
            // Create a TCP/IP socket.
            Socket listener = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

            // Bind the socket to the local endpoint and listen for incoming connections.
            try
            {
                listener.Bind(localEndPoint);
                listener.Listen(1000);

                while (!ShuttingDown)
                {
                    // Set the event to nonsignaled state.
                    allDone.Reset();
                    // Start an asynchronous socket to listen for connections.
    
                    listener.BeginAccept(new AsyncCallback(this.AcceptCallback),
                        listener);

                    // Wait until a connection is made before continuing.
                    allDone.WaitOne();
                }
            }
            catch (Exception e)
            {
                threadEnd[0].Set();
            }
        }

        /// &ltsummary>
        /// Decription: Call back method to accept new connections.
        /// </summary>
        /// &ltparam name="ar">Status of an asynchronous operation.</param>
        private void AcceptCallback(IAsyncResult ar)
        {
            // Signal the main thread to continue.
            allDone.Set();
            // Get the socket that handles the client request.
            Socket listener = (Socket) ar.AsyncState;
            Socket handler = listener.EndAccept(ar);

            // Create the state object.
            StateObject state = new StateObject();
            state.workSocket = handler;
            state.TimeStamp = DateTime.Now;

            try
            {
                Interlocked.Increment(ref sockCount);
                Monitor.Enter(connectedSocks);
                connectedSocks.Add(state);
                Monitor.Exit(connectedSocks);

                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(this.ReadCallback), state);
                if (sockCount > this.maxSockets)
                {
                    RemoveSocket(state);
                    //handler.Shutdown(SocketShutdown.Both);
                    //handler.Close();
                    handler = null;
                    state = null;
                }
            }
            catch (SocketException es)
            {
                RemoveSocket(state);
            }
            catch (Exception e)
            {
                RemoveSocket(state);
            }
        }
        /// &ltsummary>
        /// Decription: Call back method to handle incoming data.
        /// </summary>
        /// &ltparam name="ar">Status of an asynchronous operation.</param>
        protected void ReadCallback(IAsyncResult ar)
        {
            String content = String.Empty;

            // Retrieve the state object and the handler socket
            // from the async state object.
            StateObject state = (StateObject)ar.AsyncState;
            Socket handler = state.workSocket;

            try
            {
                // Read data from the client socket.
                int bytesRead = handler.EndReceive(ar);

                if (bytesRead > 0)
                {
                    // There might be more data, so store the data received so far.
                    Monitor.Enter(state);
                    state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
                    Monitor.Exit(state);

                    // Check for end-of-file tag.
                    // If it is not there, read more data.
                    content = state.sb.ToString();
                    //if (content.IndexOf("&ltEOF>") > -1)
                    if ((content.Length > 0) && ((content[0] != '<') ||
                        ((content[0] == '<') && (content.IndexOf("</message>") > -1))))
                    {
                        // All the data has been read from the
                        // client. Display it on the console.
                        //Console.WriteLine("Read {0} bytes from socket.\nData: {1}",
                        //    content.Length, content);
                        // Process the received message
                        state.TimeStamp = DateTime.Now;
                        HandleMessages(state, content);

                        // Echo the data back to the client.
                        // Send(state, content);
                        //state.sb.Length = 0;
                    }
                    else
                    {
                        // Not all data received. Get more.
                        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                            new AsyncCallback(this.ReadCallback), state);
                    }
                }
                else
                {    // Disconnected
                    RemoveSocket(state);
                }
            }
            catch (System.Net.Sockets.SocketException es)
            {
                RemoveSocket(state);
                if (es.ErrorCode != 64)
                {
                    Console.WriteLine(string.Format("ReadCallback Socket Exception: {0}, {1}.", es.ErrorCode, es.ToString()));
                }
            }
            catch (Exception e)
            {
                RemoveSocket(state);
                if (e.GetType().FullName != "System.ObjectDisposedException")
                {
                    Console.WriteLine(string.Format("ReadCallback Exception: {0}.", e.ToString()));
                }
            }
        }

        /// &ltsummary>
        /// Decription: Send the given data string to the given socket.
        /// </summary>
        /// &ltparam name="sock">Socket to send data to.</param>
        /// &ltparam name="data">The string containing the data to send.</param>
        protected void Send(Socket sock, string data)
        {
            // Convert the string data to byte data using ASCII encoding.
            byte[] byteData = Encoding.ASCII.GetBytes(data);

            // Begin sending the data to the remote device.
            if (byteData.Length > 0)
                sock.BeginSend(byteData, 0, byteData.Length, 0,
                    new AsyncCallback(this.SendCallback), sock);
        }

        /// &ltsummary>
        /// Author: Asad Aziz
        /// Decription: Call back method to handle outgoing data.
        /// </summary>
        /// &ltparam name="ar">Status of an asynchronous operation.</param>
        protected void SendCallback(IAsyncResult ar)
        {
            // Retrieve the socket from the async state object.
            Socket handler = (Socket)ar.AsyncState;
            try
            {
                // Complete sending the data to the remote device.
                int bytesSent = handler.EndSend(ar);
            }
            catch (Exception e)
            {
            }
        }

        /// &ltsummary>
        // Description: Find on socket using the identifier as the key.
        /// </summary>
        /// &ltparam name="id">The identifier key associated with a socket.</param>

        private Socket FindID(string id)
        {
            Socket sock = null;
            Monitor.Enter(connectedHT);
            if (connectedHT.ContainsKey(id))
                sock = (Socket)connectedHT[id];
            Monitor.Exit(connectedHT);
            return sock;
        }

        /// &ltsummary>
        /// Author: Asad Aziz
        /// Description: Place the given socket in the connected list.
        ///
        /// Notes:
        /// 1) Get the Member ID from the command
        /// 2) Add the socket to the connected socket list with its Member ID
        /// </summary>
        /// &ltparam name="state">The state object containing the socket info.</param>
        /// &ltparam name="command">The XML-based message containing the ID that
        /// needs to be parsed.</param>
        /// &ltparam name="content">Not used in the base method.</param>



        virtual protected bool StuffList(StateObject state, string command,
            ref string content)
        {
            Socket sock = state.workSocket;
            string hostID = ReadXML(command, Server.msgConnect, this.connectAttr);

            if (hostID != null)
            {
                state.id = hostID;
                if (hostID == Server.webServer)
                {
                    Console.WriteLine(string.Format("Host control socket connected {0}!",
                        this.title));
                    return true;
                }

                // Add to connected list
                Monitor.Enter(connectedHT);
                if (connectedHT.ContainsKey(hostID))
                {
                    object val = connectedHT[hostID];
                    connectedHT[hostID] = sock;
                    connectedHT.Add(sock, val);
                    Console.WriteLine(string.Format("Socket found in Hasttable!", this.title));
                }
                else
                {
                    connectedHT.Add(hostID, sock);
                    connectedHT.Add(sock, hostID);
                    Console.WriteLine(string.Format("Socket not found, adding a new socket to hashtable!", this.title));
                }
                Monitor.Exit(connectedHT);

                Console.WriteLine(string.Format("Socket was moved to connected {0} list!", this.title));
                return true;
            }
            return false;
        }

        /// &ltsummary>
        /// Description: Remove the socket contained in the given state object
        /// from the connected array list and hash table, then close the socket.
        /// </summary>
        /// &ltparam name="state">The StateObject containing the specific socket
        /// to remove from the connected array list and hash table.</param>
        virtual protected void RemoveSocket(StateObject state)
        {
            Socket sock = state.workSocket;
            Monitor.Enter(connectedSocks);
            if (connectedSocks.Contains(state))
            {
                connectedSocks.Remove(state);
                Interlocked.Decrement(ref sockCount);
            }
            Monitor.Exit(connectedSocks);
            Monitor.Enter(connectedHT);

            if ((sock != null) && (connectedHT.ContainsKey(sock)))
            {
                object sockTemp = connectedHT[sock];
                if (connectedHT.ContainsKey(sockTemp))
                {
                    if (connectedHT.ContainsKey(connectedHT[sockTemp]))
                    {
                        connectedHT.Remove(sock);
                        if (sock.Equals(connectedHT[sockTemp]))
                        {
                            connectedHT.Remove(sockTemp);
                        }
                        else
                        {
                            object val, key = sockTemp;
                            while (true)
                            {
                                val = connectedHT[key];
                                if (sock.Equals(val))
                                {
                                    connectedHT[key] = sockTemp;
                                    break;
                                }
                                else if (connectedHT.ContainsKey(val))
                                    key = val;
                                else    // The chain is broken
                                    break;
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine(string.Format("Socket is not in the {0}  connected hash table!", this.title));
                    }
                }
            }
            Monitor.Exit(connectedHT);

            if (sock != null)
            {
                //if (sock.Connected)
                //    sock.Shutdown(SocketShutdown.Both);
                sock.Close();
                sock = null;
                state.workSocket = null;
                state = null;

            }
        }
    }
}